﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////


#pragma once
#include "GnufItem.h"
#include "GnufLabel.h"

namespace gnuf {
    class Toolbar;
    class Text;
    class Label;
    class Check;
    class QtNameValuePair;
    class QtNameValuePairs;
    class QtNameValuePairBlock;
    class NameValuePairs;
    class NameValuePairBlock;
    class CheckGroup;
    class List;
    class ColorControl;
    class WidgetAgent;
    class ButtonEx;
    class Block;
    class CheckListButton;
    class NameValuePairGroup;
    class GNUF_BASE_EXPORT NameValuePair final
        : public ItemWith<QtNameValuePair>
    {
        CANNOT_COPY_OR_ASSIGN(NameValuePair)
        
    public:
        static const EItemType Type;
        explicit NameValuePair(Item * parent, const Info&, EItemType valueType,bool isTagNameType);
        virtual ~NameValuePair();
        
        Label * name()   { return m_name.get(); }
        const Label * name() const { return m_name.get(); }
        Item * value()  { return m_value.get(); }
        const Item * value() const { return m_value.get(); }
        bool isTagNameType() const { return m_isTagNameType; }

        void setIconAtName(gcmp::OwnerPtr<Icon>&& opIcon);

        void setDescription(const std::wstring&);
        const std::wstring& description() const { return m_description; }

    protected:
        // Inherits from Item...
        virtual void onDisconnectFromMyQtItem() override;
        
    private:
        void makeName(bool);
        void makeValue(EItemType);
        
        gcmp::OwnerPtr< Info > m_info;
        gcmp::OwnerPtr< Label > m_name;
        gcmp::OwnerPtr< Item > m_value;
        bool m_isTagNameType;
        std::wstring m_description;
    };
    
    class GNUF_BASE_EXPORT NameValuePairGroup
    {
        CANNOT_COPY_OR_ASSIGN(NameValuePairGroup)
        
    protected:
        explicit NameValuePairGroup();
        virtual ~NameValuePairGroup();
        
    public:
        typedef std::list< gcmp::OwnerPtr< Item > > Contents;
        typedef std::vector< Item * > RawContents;
        
        const NameValuePairGroup::Contents & contents() const { return m_contents; }
        NameValuePairGroup::RawContents rawContents();
        const int* nameValueColumnWidthRatio() const { return m_nameValueColumnWidthRatio; }
        void setNameValueColumnWidthRatio(int left, int right);
        inline int labelMinimumWidth() { return m_labelMinimumWidth; }

        template<typename TItem>
        TItem* addItem(const Info& info)
        {
            static_assert(std::is_base_of<Item, TItem>::value, "typename just only inherit from Item");
            auto nvp = NEW_AS_OWNER_PTR(NameValuePair, onGetSelf(), info, TItem::Type, false);
            Label* name = nvp->name();
            DBG_WARN_AND_RETURN_NULLPTR_UNLESS(name, L"断言`name`失败", L"GMEP", L"2023-03-16");
            name->enableTooltip(!info.tooltip().empty());

            // 如有有图标则设置图标
            if (!info.iconDir().empty())
            {
                nvp->setIconAtName(TransferOwnership(NEW_AS_OWNER_PTR(Icon, info.icon())));
            }

            Item* value = nvp->value();
            DBG_WARN_AND_RETURN_NULLPTR_UNLESS(value != nullptr, L"value is null", L"GMEP", L"2021-05-24");

            auto val = value->cast<TItem>();
            DBG_WARN_AND_RETURN_NULLPTR_UNLESS(val != nullptr, L"val is null", L"GMEP", L"2021-05-24");

            m_contents.push_back(TransferOwnership(nvp));
            return val;
        }

    protected:
        virtual Item * onGetSelf() = 0;
        
        NameValuePairGroup::Contents m_contents;

    private:
        int m_nameValueColumnWidthRatio[2] = { 1, 3 };
        int m_labelMinimumWidth = 40;
    };

    class GNUF_BASE_EXPORT NameValuePairs final
        : public ItemWith<QtNameValuePairs>
        , public NameValuePairGroup
    {
    public:
        static const EItemType Type;
        explicit NameValuePairs(Toolbar *);
        virtual ~NameValuePairs();

        // Add a name-value block.
        NameValuePairBlock * addNameValuePairBlock(const Info&, bool wantToCollapse);
        
        // Erase those empty name-value blocks.
        void eraseEmptyNameValuePairBlocks();

        // Clear all the contents.
        void clearContents();
        
        // Dump all the contents to the Qt implementation.
        void dumpContents();

        //Anchor with fixed size, true = Anchor left col, false = Anchor right col
        //Note: if you want to anchor large width in a small container with fixed size, 
        //      part of the nvps may be hided and need to scroll to see it.
        //      for example, if you want to anchor a fixed size in dynamic zone or in "属性面板",
        //      make sure the minWidth(in layout.xml) is large enough to hold the size.
        void AnchorWithSize(int width, bool left);

        // Set label value ratio, default is 1 : 3, left : right
        void setLayoutWidthRatio(int left, int right);

        // Reset column stretch and width to default.
        void resetLayoutColumn();

    protected:
        // Inherits from ItemWith...
        virtual void onDisconnectFromMyQtItem() override;
        // Inherits from NameValuePairGroup...
        virtual Item * onGetSelf() { return this; }
    private:
        // Set columnStretch for nvps column, recursively adjust block layout.
        void setLayoutColumnStretch(int column, int columnStretch, bool recursive = true);

        // Set column fixed width for nvps column, recursively adjust block layout.
        void setLayoutColumnFixedWidth(int column, int width, bool recursive = true);
    };

    class GNUF_BASE_EXPORT NameValuePairBlock final
        : public ItemWith<QtNameValuePairBlock>
        , public NameValuePairGroup
    {
    public:
        static const EItemType Type;
        explicit NameValuePairBlock(NameValuePairs *, const Info&, bool wantToCollapse);
        virtual ~NameValuePairBlock();
        
        // If ture, show a button by which the user can collapse or expand
        // this name-value block. If false, expanded always.
        bool wantToCollapse() const { return m_wantToCollapse; }

        void setLayoutColumnStretch(int column, int columnStretch);
        void setLayoutColumnFixedWidth(int column, int width);

    protected:
        // Inherits from ItemWith...
        virtual void onDisconnectFromMyQtItem() override;
        // Inherits from Item...
        virtual void onPostAppearanceSettingChanged() override;
        // Inherits from NameValuePairGroup...
        virtual Item * onGetSelf() { return this; }
        
    private:
        gcmp::OwnerPtr< Info > m_info;
        const bool m_wantToCollapse;
    };
}
